﻿using System;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;
using System.Xml;

namespace n2n_client_runner
{
    public partial class Form1 : Form
    {

        Process edge = new Process();
        bool connected = false;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            if (!File.Exists(@"./config.xml"))
            {
                CreateNewConfigXML();
            }

            if (!File.Exists(@"./mac.xml"))
            {
                CreateNewMACXML();
            }

            while (Program.GetNatAdapterName() == "") Program.OpenTap();
            XmlDocument xd = new XmlDocument();
            xd.Load("config.xml");
            string server = xd["config"]["Server"]["ip"].InnerText;
            string port = xd["config"]["Server"]["port"].InnerText;
            textBox_server.Text = server;
            textBox_port.Text = port;
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = true;
            this.WindowState = FormWindowState.Minimized;
            this.Hide();
        }

        private void CreateNewMACXML()
        {
            XmlDocument xd = new XmlDocument();
            XmlDeclaration xdt = xd.CreateXmlDeclaration("1.0", "utf-8", null);
            xd.AppendChild(xdt);
            XmlElement Root = xd.CreateElement("MAC");
            xd.AppendChild(Root);
            XmlElement Address = xd.CreateElement("Address");
            Address.InnerText = Program.GenerateMACAddress();
            Root.AppendChild(Address);
            xd.Save("mac.xml");
        }

        private void CreateNewConfigXML()
        {
            XmlDocument xd = new XmlDocument();
            XmlDeclaration xdt = xd.CreateXmlDeclaration("1.0", "utf-8", null);
            xd.AppendChild(xdt);
            XmlElement Root = xd.CreateElement("config");
            xd.AppendChild(Root);
            XmlElement Server = xd.CreateElement("Server");
            XmlElement server = xd.CreateElement("ip");
            server.InnerText = "example.org";
            XmlElement port = xd.CreateElement("port");
            port.InnerText = "10000";
            XmlElement dhcpd = xd.CreateElement("dhcpd");
            dhcpd.InnerText = "dhcp:10.6.8.1";
            XmlElement relay = xd.CreateElement("relay");
            relay.InnerText = false.ToString();
            Server.AppendChild(server);
            Server.AppendChild(port);
            Server.AppendChild(dhcpd);
            Server.AppendChild(relay);
            Root.AppendChild(Server);
            XmlElement Client = xd.CreateElement("Client");
            XmlElement community = xd.CreateElement("community");
            community.InnerText = "n2n";
            XmlElement key = xd.CreateElement("key");
            key.InnerText = "clientrunner";
            Client.AppendChild(community);
            Client.AppendChild(key);
            Root.AppendChild(Client);
            xd.Save("config.xml");
        }

        private void RunClient(bool run)
        {
            if (run)
            {
                XmlDocument xd = new XmlDocument();
                xd.Load("config.xml");
                Process[] old = Process.GetProcessesByName("edge");
                for (int i = 0; i < old.Length; i++)
                {
                    old[i].Kill();
                }
                string args = "-d \"" + Program.GetNatAdapterName() + "\" -c "+ xd["config"]["Client"]["community"].InnerText + " -k "+ xd["config"]["Client"]["key"].InnerText + " -l " + textBox_server.Text + ":" + textBox_port.Text +" -r -a " + xd["config"]["Server"]["dhcpd"].InnerText + " -p 9876";
                if (Convert.ToBoolean(xd["config"]["Server"]["relay"].InnerText))
                {
                    args += " -S";
                }
                xd.Load("mac.xml");
                args += " -m " + xd["MAC"]["Address"].InnerText;
                Console.WriteLine(args);
                ProcessStartInfo startInfo = new ProcessStartInfo("bin/edge.exe", args);
                startInfo.UseShellExecute = false;
                startInfo.RedirectStandardOutput = true;
                startInfo.RedirectStandardError = true;
                startInfo.CreateNoWindow = true; 
                startInfo.WindowStyle = ProcessWindowStyle.Hidden;
                edge.StartInfo = startInfo;
                edge.Start();
            }
            else
            {
                edge.Kill();
                edge.Close();
            }
                        
        }

        private void Self_MenuItem_Click(object sender, EventArgs e)
        {
            this.Show();
            this.WindowState = FormWindowState.Normal;
        }

        private void Exit_MenuItem_Click(object sender, EventArgs e)
        {
            if (connected)
            {
                edge.Kill();
                edge.Close();
            }
            this.Dispose();
            this.Close();
        }

        private void Button_Connect_Click(object sender, EventArgs e)
        {
            XmlDocument xd = new XmlDocument();
            xd.Load("config.xml");
            xd["config"]["Server"]["ip"].InnerText = textBox_server.Text;
            xd["config"]["Server"]["port"].InnerText = textBox_port.Text;
            xd.Save("config.xml");

            if (connected)
            {
                textBox_server.Enabled = true;
                textBox_port.Enabled = true;
                connected = false;
                button_connect.Text = "连接";
                RunClient(connected);
            }
            else
            {
                textBox_server.Enabled = false;
                textBox_port.Enabled = false;
                connected = true;
                button_connect.Text = "断开";
                RunClient(connected);
            }
        }

        private void TrayIcon_Click(object sender, MouseEventArgs e)
        {
            if(this.WindowState == FormWindowState.Minimized)
            {
                this.Show();
                this.WindowState = FormWindowState.Normal;
            }
        }
    }
}
